﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web.Security;
using AutoMapper;
using SklepISI.Core.Helpers;
using SklepISI.Core.Interfaces;
using SklepISI.Core.Models;

namespace SklepISI.Core.Services
{
    public class UserService : IUserService
    {
        public bool ValidUser(string login, string password)
        {
            using (var ctx = new Entities())
            {
                string hash = StringEncrypt.Generate(password);
                var dbUser = ctx.Users.FirstOrDefault(user => user.Username.ToLower() == login &&
                                                 user.Password == hash);

                return (dbUser != null);
            }
        }

        public System.Web.Security.MembershipCreateStatus CreateUser(Models.UserModel user)
        {
            MembershipCreateStatus status;
            using (var ctx = new Entities())
            {
                if (ctx.Users.Any(x => x.Email == user.Email))
                    status = MembershipCreateStatus.DuplicateEmail;
                else if (ctx.Users.Any(x => x.Username == user.Username))
                    status = MembershipCreateStatus.DuplicateUserName;
                else
                {
                    var usr = Mapper.Map<UserModel, User>(user);

                    usr.Password = StringEncrypt.Generate(usr.Password); // <-- cruel, sorry about that

                    ctx.Users.Add(usr);
                    ctx.SaveChanges();
                    status = MembershipCreateStatus.Success;
                }
            }
            return status;
        }

        public int GetRoleID(string userName)
        {
            using (var ctx = new Entities())
            {
                var dbUser = ctx.Users.FirstOrDefault(u => u.Username == userName);
                if (dbUser == null)
                    throw new ArgumentException();
                return dbUser.RoleID;
            }
        }

        public bool ChangeUserRole(string userName, int roleId)
        {
            using (var ctx = new Entities())
            {
                var dbRole = ctx.Roles.FirstOrDefault(r => r.ID == roleId);
                if (dbRole == null)
                {
                    throw new ArgumentException();
                }
                else
                {
                    var dbUser = ctx.Users.FirstOrDefault(u => u.Username == userName);
                    if (dbUser == null)
                        throw new ArgumentException();

                    dbUser.RoleID = roleId;
                    ctx.Entry(dbUser).State = EntityState.Modified;
                    ctx.SaveChanges();
                    return true;
                }
            }
        }


        public bool RemoveUser(string userName)
        {
            bool result = false;
            using (var ctx = new Entities())
            {
                var dbUser = ctx.Users.Include("Orders").FirstOrDefault(u => u.Username == userName);
                List<OrderContent> orderContentsToDelete = new List<OrderContent>();
                List<Order> ordersToDelete = new List<Order>();
                if (dbUser != null)
                {
                    foreach (var order in dbUser.Orders)
                    {
                        foreach (var content in order.OrderContents)
                        {
                            orderContentsToDelete.Add(content);
                        }
                        ordersToDelete.Add(order);
                    }

                    //delete
                    foreach (var orderContent in orderContentsToDelete)
                    {
                        ctx.OrderContents.Remove(orderContent);
                    }

                    foreach (var order in ordersToDelete)
                    {
                        ctx.Orders.Remove(order);
                    }

                    ctx.Users.Remove(dbUser);
                    ctx.SaveChanges();
                    result = true;
                }


            }
            return result;
        }


        public bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            if (String.IsNullOrEmpty(userName) || String.IsNullOrEmpty(oldPassword) || String.IsNullOrEmpty(newPassword))
            {
                return false;
            }

            var result = false;
            using (var ctx = new Entities())
            {
                string oldPasswordHash = StringEncrypt.Generate(oldPassword);
                var dbUser = ctx.Users.FirstOrDefault(u => u.Username == userName && u.Password == oldPasswordHash);
                if (dbUser != null)
                {
                    var newPasswordHash = StringEncrypt.Generate(newPassword);
                    dbUser.Password = newPasswordHash;
                    ctx.Entry(dbUser).State = EntityState.Modified;
                    ctx.SaveChanges();
                    result = true;
                }
            }
            return result;
        }

        public UserModel GetUser(string userName)
        {
            using (var ctx = new Entities())
            {
                var tmp = ctx.Users.Where(p => p.Username == userName).SingleOrDefault();
                
                return Mapper.Map<User, UserModel>(tmp);
            }
        }

        public UserModel GetUserById(int id)
        {
            using (var ctx = new Entities())
            {
                var tmp = ctx.Users.Where(p => p.ID == id).SingleOrDefault();

                return Mapper.Map<User, UserModel>(tmp);
            }
        }
    }
}
